package com.weixin;

import java.io.BufferedReader;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gesonet.pay.utils.HttpsUtils;
import com.gesonet.pay.utils.PayCommonUtil;
import com.gesonet.pay.utils.XmlUtil;
import com.weixin.model.Token;
import com.weixin.model.WxCallbackReq;
import com.weixin.model.WxPrePayReq;
import com.weixin.model.WxPrePayRes;

import net.sf.json.JSONException;
import net.sf.json.JSONObject;

public class WechatPay {
	
	private static final Logger logger = LoggerFactory.getLogger(WechatPay.class);

	public static final String EXTRA_SIGN_KEY = "key="+WechatConfig.API_KEY;
	
	public static final String RETURN_CODE_SUCCESS = "SUCCESS";
	public static final String RETURN_CODE_FAIL = "FAIL";
	public static final String RETURN_MSG_OK = "OK";
	/**
	 * 获取接口访问凭证
	 * @param appid 凭证
	 * @param appsecret 密钥
	 * @return
	 */
	public static Token getToken(String appid, String appsecret) {
		Token token = null;
		String requestUrl = WechatConfig.TOKEN_URL.replace("APPID", appid).replace("APPSECRET", appsecret);
		// 发起GET请求获取凭证
		String res = HttpsUtils.httpsRequest(requestUrl, "GET", null);
		
		JSONObject jsonObject = JSONObject.fromObject(res);

		if (null != jsonObject) {
			try {
				token = new Token();
				token.setAccessToken(jsonObject.getString("access_token"));
				token.setExpiresIn(jsonObject.getInt("expires_in"));
			} catch (JSONException e) {
				token = null;
				// 获取token失败
				logger.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"),
						jsonObject.getString("errmsg"));
			}
		}
		return token;
	}
	
	
	/**
	 * 获取微信下单请求的响应数据<prepayid>等
	 * @param req 微信支付下单请求数据模型
	 * @return 下单请求响应的xml数据
	 * @throws Exception 未知异常，可能为https异常或解析响应数据异常
	 */
	public static WxPrePayRes getPrePayXml(WxPrePayReq req) throws Exception{
		
		String sign = PayCommonUtil.createObjMD5Sign(req, EXTRA_SIGN_KEY);
		req.setSign(sign);
		
		String reqXml = XmlUtil.obj2Xml(req);
		logger.debug("下单请求数据：{}",reqXml);
		String resXml = HttpsUtils.httpsRequest(WechatConfig.UNIFIED_ORDER_URL, "POST", reqXml);
		logger.debug("下单返回数据：{}",resXml);
		
		WxPrePayRes res = new WxPrePayRes(RETURN_CODE_FAIL);
		if(StringUtils.isBlank(resXml)){
			return res;
		}
		Map<String,String> retsultMap = XmlUtil.parseXml(resXml);
		
		SortedMap<String, String> paramsForPage = new TreeMap<String, String>();
		//map中有return_code和result_code两个字段,只有当这两个字段的值都为SUCCESS的时候，prepay_id才有值
		String return_code = retsultMap.get("return_code");
		String result_code = retsultMap.get("result_code");
		if ("SUCCESS".equalsIgnoreCase(return_code) && "SUCCESS".equalsIgnoreCase(result_code)) {
			String prepayId = retsultMap.get("prepay_id");
			String packageValue = "prepay_id="+prepayId;
			//JSAPI支付接口只需要六个参数
			String timeStamp = PayCommonUtil.createTimestamp();
			String nonceStr = PayCommonUtil.createNonceStr();
	        paramsForPage.put("appId", WechatConfig.APPID);
	        paramsForPage.put("timeStamp", timeStamp);
	        paramsForPage.put("nonceStr", nonceStr);
	        paramsForPage.put("package", packageValue);
	        paramsForPage.put("signType", "MD5");
	        String paySign =  PayCommonUtil.createMapMD5Sign(paramsForPage, EXTRA_SIGN_KEY);
	        return new WxPrePayRes(packageValue, paySign,timeStamp,nonceStr, result_code, RETURN_MSG_OK, prepayId);
		} else {
			logger.debug("return_code={}",return_code);
			logger.debug("result_code={}",result_code);
		}
		return res;
	}
	
	
	/**
	 * @author qin
	 * @description 封装客户端调起微信app支付数据
	 * @param dataMap 微信支付下单响应的数据
	 * @return 客户端调起微信App的数据
	 */
	public static SortedMap<String,String> getInvokePayData(Map<String,String> dataMap){
		SortedMap<String,String> sortedMap = new TreeMap<>();
		String resultCode = dataMap.get("result_code");
		if("SUCCESS".equals(resultCode)){
			sortedMap.put("appid", WechatConfig.APPID);
			sortedMap.put("partnerid", WechatConfig.MCH_ID);
			sortedMap.put("prepayid", dataMap.get("prepay_id"));
			sortedMap.put("package", "Sign=WXPay");
			sortedMap.put("noncestr", PayCommonUtil.createNonceStr());
			sortedMap.put("timestamp", String.valueOf(System.currentTimeMillis()/1000));
			sortedMap.put("sign", PayCommonUtil.createMapMD5Sign(sortedMap,EXTRA_SIGN_KEY));
//			sortedMap.put("packageValue", "Sign=WXPay");
//			sortedMap.remove("package");
		}else{
			logger.error("下单失败，响应结果不为成功:{}",dataMap);
		}
		logger.debug("响应给客户端的封装的数据:{}",sortedMap);
		return sortedMap;
	}
	
	/**
	 * 微信回调接口时获取微信的请求参数
	 * @param request
	 * @return
	 * @throws Exception
	 */
	public static WxCallbackReq getCallbackData(HttpServletRequest request) throws Exception{
		BufferedReader bis = new BufferedReader(new java.io.InputStreamReader(request.getInputStream()));
		String line = null;
		String result = "";
		try {
			while ((line = bis.readLine()) != null) {
				result += line + "\r\n";
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			bis.close();
		}
		if(StringUtils.isNotBlank(result)){
			return (WxCallbackReq) XmlUtil.xml2Object(result, WxCallbackReq.class);
		}
		return null;
	}
	
	/**
	 * @date 2014-12-3上午10:17:43
	 * @Description：返回给微信的xml数据
	 * @param return_code 返回编码
	 * @param return_msg  返回信息
	 * @return
	 */
	public static String successResponseXML(String return_code, String return_msg) {
		return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg
				+ "]]></return_msg></xml>";
	}
	
	
}
